package com.baizhi.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;

/**
 * ClassName: WebSecurityConfigurer
 * Description:
 * Date: 2022/11/03 AM 10:34
 * <p>
 * project: codes
 * package: com.baizhi.config
 * email: 1085844536@qq.com
 * version:
 *
 * @author WangGuojian
 */
@Configuration
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {

    private final MyUserDetailServiceImpl myUserDetailServiceImpl;

    /**
     * Creates an instance with the default configuration enabled.
     */
    @Autowired
    public WebSecurityConfigurer(MyUserDetailServiceImpl myUserDetailServiceImpl) {
        this.myUserDetailServiceImpl = myUserDetailServiceImpl;
    }

    //@Bean
    //public UserDetailsService userDetailsService() {
    //    InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
    //    userDetailsService.createUser(User.withUsername("aaa").password("{noop}123").roles("admin").build());
    //    return userDetailsService;
    //}

    /**
     * springboot 对 security 默认配置中   在工厂中默认创建 AuthenticationManager
     */
    //@Autowired
    //public void initialize(AuthenticationManagerBuilder builder) throws Exception {
    //    System.out.println("spring boot 中默认配置：" + builder);
    //
    //    builder.userDetailsService(userDetailsService);
    //}

    /**
     * 自定义 AuthenticationManager 推荐
     */
    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception {
        System.out.println("自定义AuthenticationManager：" + builder);
        // daoAuthenticationProvider
        builder.userDetailsService(myUserDetailServiceImpl);
    }

    /**
     * 作用：用来将自定义 AuthenticationManager 在工厂中进行暴露，可以在任何位置注入
     *
     * @return
     * @throws Exception
     */
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // 放行资源写在前面
                .mvcMatchers("/login.html").permitAll()
                .mvcMatchers("/index").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                // 用来指定默认登陆界面 注意：一旦自定义登陆界面后必须指定登陆 url
                .loginPage("/login.html")
                // 指定处理登陆请求 url
                .loginProcessingUrl("/doLogin")
                .usernameParameter("uname")
                .passwordParameter("passwd")
                // 认证成功 forward 跳转路径 始终在认证成功之后跳转到指定请求
                //.successForwardUrl("/index")
                // 默认认证成功之后的 redirect 跳转 根据上一条保存请求进行成功跳转
                //.defaultSuccessUrl("/index", true)
                // 认证成功时的处理 前后端分离解决方案
                .successHandler(new MyAuthenticationSuccessHandler())
                // 认证失败之后 forward 跳转
                //.failureForwardUrl("/login.html")
                // 认证失败之后 redirect 跳转
                //.failureUrl("/login.html")
                // 用来自定义失败之后的处理 前后端分离的解决方案
                .failureHandler(new MyAuthenticationFailureHandler())
                .and()
                .logout()
                // 指定注销登陆 url 默认请求方式必须：GET
                //.logoutUrl("/logout")
                .logoutRequestMatcher(new OrRequestMatcher(
                        new AntPathRequestMatcher("/aa", "GET"),
                        new AntPathRequestMatcher("/bb", "POST")
                ))
                // 默认 会话失效
                .invalidateHttpSession(true)
                // 默认 清除认证标记
                .clearAuthentication(true)
                // 注销登陆 成功之后跳转页面
                //.logoutSuccessUrl("/login.html")
                // 注销登陆成功之后的处理
                .logoutSuccessHandler(new MyLogoutSuccessHandler())
                .and()
                // 禁止 csrf 跨站请求保护
                .csrf().disable();
    }
}
